<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>04_Proxy-监听函数对象操作方法</title>
  <!-- 
  在 JavaScript 中， `Proxy`  可以用于监听和自定义对函数对象的操作。通过使用  `Proxy` ，你可以拦截函数的调用、构造和其他操作。
  1. Proxy 的基本概念
  `Proxy`  是一个用于定义自定义行为的对象，它可以拦截对目标对象的基本操作，如属性访问、赋值、函数调用等。

  2. 监听函数对象操作的方法

  2.1 监听函数调用 ( `apply` )
  - 用途：当代理的目标是一个函数时，可以使用  `apply`  捕获器来定义自定义的函数调用行为。
  - 用法：可以拦截对函数的调用，并在调用前后执行自定义逻辑。
  const targetFunction = function(x, y) {
      return x + y;
  };

  const handler = {
      apply: function(target, thisArg, argumentsList) {
          console.log(`Calling function with arguments: ${argumentsList}`);
          // 调用原始函数
          return target.apply(thisArg, argumentsList);
      }
  };

  const proxyFunction = new Proxy(targetFunction, handler);
  console.log(proxyFunction(2, 3)); // 输出: Calling function with arguments: 2,3
                                    // 输出: 5
  2.2 监听构造函数调用 ( `construct` )
  - 用途：当代理的目标是一个构造函数时，可以使用  `construct`  捕获器来定义自定义的构造行为。
  - 用法：可以拦截对构造函数的调用，并在创建实例前后执行自定义逻辑。
  function Person(name) {
      this.name = name;
  }

  const handler = {
      construct: function(target, args) {
          console.log(`Creating a new instance with arguments: ${args}`);
          // 创建并返回新实例
          return new target(...args);
      }
  };

  const ProxyPerson = new Proxy(Person, handler);
  const personInstance = new ProxyPerson('Alice'); // 输出: Creating a new instance with arguments: Alice
  console.log(personInstance.name); // 输出: Alice
  3. 总结
  使用  `Proxy`  监听函数对象的操作可以帮助开发者实现更灵活和强大的函数行为。通过  `apply`  和  `construct`  捕获器，开发者可以拦截函数调用和构造函数调用，执行自定义的逻辑。这种机制为函数的监控、调试和增强提供了强大的工具。理解这些捕获器的用法对于编写高效和可维护的 JavaScript 代码非常重要。
  -->
</head>

<body>

  <script>

    function foo(num1, num2) {
      console.log(this, num1, num2)
    }

    const p = new Proxy(foo, {
      // apply属性：拦截函数调用
      apply: function (target, thisArg, argumentsList) {
        console.log(target, thisArg, argumentsList);
        return target.apply(thisArg, argumentsList);
      },
      // construct属性：拦截构造函数调用
      construct: function (target, argumentsList, newTarget) {
        console.log(target, argumentsList, newTarget);
        return new target(...argumentsList);
      }
    })
    
    const resApply = p.apply({ name: 'Alice' }, [1, 2]); // 输出: Calling function with arguments: [1, 2]
    const resConstruct = new p(1, 2); // 输出: Constructing a new instance with arguments: [1, 2]
    console.log(resApply, resConstruct);


  </script>

</body>

</html>